package com.oceansoft.mobile.econsole.modules.message.entity;

import com.oceansoft.mobile.econsole.modules.message.util.Utils;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ExceptionCommonBase extends Exception implements IExceptionCommon {

    private static final long serialVersionUID = -4594875950045103211L;
    private static final Pattern pattern = Pattern.compile("ErrorCode:(-[0-9]*) / Message:");

    protected int errorCode = -1;

    private Throwable cause = null;

    private String message = null;

    public static String errorCodeMessage(int errorCode) {
        return errorCodeMessage(errorCode, null);
    }

    public static String errorCodeMessage(int errorCode, String message) {
        return "ErrorCode:" + errorCode + " / Message:" + message;
    }

    public static boolean isDuplicateKeyException(Throwable ex) {
        return ex.toString().indexOf("MySQLIntegrityConstraintViolationException: Duplicate entry") > 0;
    }

    public static boolean isDatabaseIntegrityConstraintViolation(Throwable ex) {
        return ex.toString().indexOf("MySQLIntegrityConstraintViolationException") > 0;
    }

    public static boolean isOutOfMemory(Throwable ex) {
        return ex.toString().indexOf("java.lang.OutOfMemoryError: Java heap space") > 0;
    }

    public static int parseErrorCode(String reason, int defaultValue) {
        Matcher matcher = pattern.matcher(reason);
        if (matcher.find()) {
            String errorCode = matcher.group(1);
            return Integer.parseInt(errorCode);
        }
        return defaultValue;
    }

    public static int parseErrorCode(Throwable ex, int defaultValue) {
        if (ex != null) {
            if ((ex instanceof IExceptionCommon)) {
                return ((IExceptionCommon) ex).getErrorCode();
            }
            Throwable cause = ex.getCause();
            if ((cause instanceof IExceptionCommon))
                return ((IExceptionCommon) cause).getErrorCode();
            return parseErrorCode(ex.toString(), defaultValue);
        }
        return defaultValue;
    }

    public static void releaseMemory() {
        try {
            System.gc();
        } catch (Throwable localThrowable) {
            localThrowable.printStackTrace();
        }
    }

    private static void resetErrorCode(ExceptionCommonBase e) {
        if (e != null) {
            if (e.cause != null) {
                int errorCode = parseErrorCode(e.cause, 0);
                if (errorCode < 0) {
                    e.setErrorCode(errorCode);
                    return;
                }
            }
            int errorCode = parseErrorCode(e.getMessage(), 0);
            if (errorCode < 0)
                e.setErrorCode(errorCode);
        }
    }

    public static void resetErrorCode(Throwable e) {
    }

    public static ExceptionCommonBase throwExceptionCommonBase(Throwable ex) throws ExceptionCommonBase {
        if ((ex instanceof ExceptionCommonBase))
            return (ExceptionCommonBase) ex;
        if ((ex instanceof IExceptionCommon)) {
            IExceptionCommon e = (IExceptionCommon) ex;
            return new ExceptionCommonBase(e.getErrorCode(), ex);
        }
        return new ExceptionCommonBase(-1, "网络连接异常");
    }

    public ExceptionCommonBase(int errorCode) {
        this(errorCode, null, null);
    }

    public ExceptionCommonBase(int errorCode, String message) {
        this(errorCode, message, null);
    }

    public ExceptionCommonBase(int errorCode, String message, Throwable cause) {
        this.errorCode = errorCode;
        this.message = message;
        this.cause = cause;
    }

    public ExceptionCommonBase(int errorCode, Throwable cause) {
        this(errorCode, null, cause);
    }

    public int getErrorCode() {
        return this.errorCode;
    }

    public String getMessage() {
        if ((this.cause != null) && (Utils.stringIsNullOrEmpty(this.message)))
            this.message = this.cause.getMessage();
        return "ErrorCode:" + getErrorCode() + " / Message:" + this.message;
    }

    public void printStackTrace() {
        super.printStackTrace();
        if (this.cause != null)
            this.cause.printStackTrace();
    }

    public void printStackTrace(PrintStream ps) {
        super.printStackTrace(ps);
        if (this.cause != null)
            this.cause.printStackTrace(ps);
    }

    public void printStackTrace(PrintWriter pw) {
        super.printStackTrace(pw);
        if (this.cause != null)
            this.cause.printStackTrace(pw);
    }

    public void resetErrorCode() {
        resetErrorCode(this);
    }

    public void setErrorCode(int errorCode) {
        this.errorCode = errorCode;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}